#pragma once
#include <functional>
#include <string>
#include <signal.h>
#include "Socket.hpp"
#include "log.hpp"
#include "Protocol.hpp"
#include "TCP_Calculator.hpp"

//包装器
using func_t = std::function<std::string(std::string &package)>;

const uint16_t defaultport =8080;


class TCPserver
{
public:
    TCPserver(uint16_t port ,func_t callclk )
    :_port(port)
    ,_callclk(callclk)
    {
    }

    //建立TCP链接
    void InitTCPServer()
    {
        _socket.Socket();
        _socket.Bind(_port);
        _socket.Listen();
        cout<<"监听中...... 端口号:%d  \n"<<_port<<endl;
    }
    //对报文进行解包并打包发送结果
    void Start()
    {
        signal(SIGCHLD, SIG_IGN);  //自动回收子进程，防止成为僵尸进程
        signal(SIGPIPE, SIG_IGN);  //：当向一个已关闭的管道或套接字写数据时，系统会发送 SIGPIPE 信号，通常会导致进程终止
        
        while(1)
        {
            //监听套接字  阻塞式
            string clientip;
            uint16_t clientport;
            int sockfd=_socket.Accept(clientip,&clientport);   //双方通信的文件描述符
            //多进程
            pid_t id=fork(); 
            if(id<0)
            {
                lg(Fatal, "error fork: %s, error code: %d", strerror(errno), errno);
                exit(-5);
            }
            //子进程
            else if(id==0)
            {
                
                string Send_package;
                std::string inbuffer;
                while(true)
                {
                    char recieve_buf[1024];
                    ssize_t n=read(sockfd,recieve_buf,sizeof(recieve_buf));
                    if(n>0)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
                    { 
                        recieve_buf[n]=0;
                        inbuffer+=recieve_buf;
                        lg(Debug,"inbuffer:%s ",inbuffer.c_str());
                        

                        //读到的报文不只一个，需要循环读取
                        while(true)
                        {
                            //解析、打包、发送,同时对报文往后进行解析
                            Send_package=_callclk(inbuffer);
                            if(Send_package.empty())
                            break;
                            lg(Debug,"Send_package:%s ",Send_package.c_str());
                            lg(Debug,"inbuffer:\n %s ",inbuffer.c_str());
                            write(sockfd,Send_package.c_str(),Send_package.size());
                            sleep(1);
                        }
                
                    }
                    else if(n==0)
                        break;
                    else
                        break;
                }
                //说明读取完毕或者读出问题了，退出进程
                exit(0);   
            }
            close(sockfd);
        }

    
    }
    ~TCPserver()
    {}

private:
    uint16_t _port; 
    string _ip;  
    Sock _socket;
    func_t _callclk;  //对
};